package com.yourenbang.lingyun.transaction.web.service.impl.yxy;

import com.alibaba.fastjson.JSONObject;
import com.yourenbang.lingyun.constants.BizCodeMessages;
import com.yourenbang.lingyun.constants.enums.ChannelIdEnums;
import com.yourenbang.lingyun.constants.enums.PlatNoEnums;
import com.yourenbang.lingyun.constants.enums.pay.PayFromEnum;
import com.yourenbang.lingyun.constants.enums.pay.PayTypeEnum;
import com.yourenbang.lingyun.constants.enums.table.MerchantEnum;
import com.yourenbang.lingyun.constants.enums.table.PayTransactionEnum;
import com.yourenbang.lingyun.core.base.bean.SpringContextUtils;
import com.yourenbang.lingyun.core.message.Result;
import com.yourenbang.lingyun.core.util.KLog;
import com.yourenbang.lingyun.core.util.StringUtils;
import com.yourenbang.lingyun.core.util.date.DateFormat;
import com.yourenbang.lingyun.core.util.date.LocalDateUtils;
import com.yourenbang.lingyun.core.util.encrypt.xiaolu.XiaoLuUtil;
import com.yourenbang.lingyun.domain.Merchant21;
import com.yourenbang.lingyun.domain.Merchant21Example;
import com.yourenbang.lingyun.domain.Terminal;
import com.yourenbang.lingyun.domain.Terminal21;
import com.yourenbang.lingyun.mapper.Merchant21Mapper;
import com.yourenbang.lingyun.transaction.constant.LklTransTypeEnum;
import com.yourenbang.lingyun.transaction.mapper.TransactionPayTransactionMapper;
import com.yourenbang.lingyun.transaction.util.DateUtil;
import com.yourenbang.lingyun.transaction.util.PayTransactionUtil;
import com.yourenbang.lingyun.transaction.web.service.CommonService;
import com.yourenbang.lingyun.transaction.web.service.pay.PayTransactionOrderService;
import com.yourenbang.lingyun.transaction.web.service.pay.klks.PayEposService;
import com.yourenbang.lingyun.transaction.web.service.yxy.XiaoLuTradeService;
import com.yourenbang.lingyun.transaction.web.service.yxy.YxyTradeService;
import com.yourenbang.merchant.api.model.dto.CheckActiveRewardYxyDTO;
import com.yourenbang.merchant.api.model.dto.SaveMerchantDTO;
import com.yourenbang.merchant.api.model.dto.YsPaySaveMerchantDTO;
import com.yourenbang.merchant.api.service.yxy.MerchantYxyApiService;
import com.yourenbang.merchant.api.service.yxy.MerchantYxyRewardApiService;
import com.yourenbang.terminal.api.model.dto.RpcYxyCallbackBindDTO;
import com.yourenbang.terminal.api.service.RpcYxyTerminalService;
import com.yourenbang.transaction.api.model.vo.pay.PayTransaction;
import com.yourenbang.transaction.api.service.pay.PayTypeApiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static jodd.util.ThreadUtil.sleep;

/**
 * @Description
 * @Date 2021/4/26 15:13
 * @Created by Jason
 */
@Slf4j
@Service
public class XiaoLuTradeServiceImpl implements XiaoLuTradeService {

    @Autowired
    MerchantYxyApiService merchantYxyApiService;

    @Autowired
    RpcYxyTerminalService rpcYxyTerminalService;

    @Autowired
    Merchant21Mapper merchant21Mapper;

    @Autowired
    private MerchantYxyRewardApiService merchantYxyRewardApiService;

    @Autowired
    private PayEposService payEposService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private YxyTradeService yxyTradeService;

    @Autowired
    private PayTypeApiService payTypeApiService;

    @Autowired
    private TransactionPayTransactionMapper transactionPayTransactionMapper;

    @Autowired
    private PayTransactionOrderService payTransactionOrderService;
    /**
     * 商户通知
     *
     * @param jsonObject
     * @return
     */
    @Override
    public Result eposMerchantNotify(JSONObject jsonObject) {
        log.info("小陆商户通知");
        if (commonService.repeatSubmit("callbackXiaolu-merchantNotify:" + jsonObject.getString("mercid"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }
        String merchantNo = jsonObject.getString("mercid");
        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);

        String secret = jsonObject.getString("reqdata");
        JSONObject jSecret = new JSONObject();
        if (!StringUtils.isEmpty(secret)) {
            Map<String, String> payParams = payTypeApiService.getPayParams(PayTypeEnum.XIAO_LU_EPOS, PayFromEnum.merchant);
            jSecret = JSONObject.parseObject(XiaoLuUtil.sm4Decrypt(payParams.get("key"), secret));
        }
        if (Objects.isNull(merchant21)) {
            SaveMerchantDTO dto = new SaveMerchantDTO();
            dto.setMerchantNo(merchantNo);
            dto.setAgentNo(jsonObject.getString("agentid"));
            dto.setRegistTime(DateUtil.getDateTime());
            dto.setAuthTime(DateUtil.getDateTime());
            dto.setActiveTime(DateUtil.getDateTime());
            dto.setUserName(jsonObject.getString("mercname"));
            dto.setPhone(merchantNo);

            dto.setRealName(jSecret.getString("name"));
            dto.setIdCard(jSecret.getString("idcard"));

            dto.setChannelId(ChannelIdEnums.YRB_XIAOLU_EPOS.getCode());
            dto.setPushWay(YsPaySaveMerchantDTO.PUSH_WAY_MERCHANT);
            return merchantYxyApiService.saveMerchant(dto);
        } else {
            Merchant21 merchant21Update = new Merchant21();
            merchant21Update.setMerchantId(merchant21.getMerchantId());
            merchant21Update.setRealName(jSecret.getString("name"));
            merchant21Update.setIdCard(jSecret.getString("idcard"));
            merchant21Mapper.updateByPrimaryKeySelective(merchant21Update);
            return Result.builder().success();
        }
    }

    /**
     * 机具绑定通知
     *
     * @param jsonObject
     * @return
     */
    @Override
    public Result eposIccNotify(JSONObject jsonObject) {

        log.info("易生机具绑定通知");

        if (commonService.repeatSubmit("callbackXiaolu-bindPosNotify:" + jsonObject.getString("cusNo"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }

        String bindResult = jsonObject.getString("result");
        if (Objects.nonNull(bindResult) && StringUtils.equals(bindResult, "00")) {

            String merchantNo = jsonObject.getString("shopNo");
            String terminalSn = jsonObject.getString("possNo");
            String bindTime = jsonObject.getString("bindTime");

            Terminal21 terminal21 = rpcYxyTerminalService.getTerminalBySn(terminalSn);
            if (Objects.isNull(terminal21)) {
                log.error("易生交易推送,机具不存在.");
                return Result.builder().fail();
            }

            Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
            if (Objects.isNull(merchant21)) {
                log.info("易生交易推送,商户不存在插入");

                Map<String, String> payParams = payTypeApiService.getPayParams(PayTypeEnum.YI_SHENG, PayFromEnum.merchant);
                SaveMerchantDTO dto = new SaveMerchantDTO();
                dto.setMerchantNo(merchantNo);
                dto.setUserName(jsonObject.getString("shopName"));
                dto.setAgentNo(payParams.get("agentid"));
                dto.setRegistTime(jsonObject.getString("bindTime"));
                dto.setAuthTime(jsonObject.getString("bindTime"));
                dto.setActiveTime(jsonObject.getString("bindTime"));
                dto.setTerminalSn(terminalSn);
                dto.setUnionpayMerchantNo(jsonObject.getString("cusNo"));
                dto.setChannelId(ChannelIdEnums.YRB_YS_EPOS.getCode());
                dto.setPushWay(YsPaySaveMerchantDTO.PUSH_WAY_MERCHANT);
                merchantYxyApiService.saveMerchant(dto);
                merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
            }

            String bindUserBaseId = terminal21.getBindUserBaseId();
            if (StringUtils.isNotEmpty(bindUserBaseId)) {
                if (StringUtils.equals(merchant21.getUserBaseId(), bindUserBaseId)) {
                    log.info("机具已绑定，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
                    return Result.builder().success();
                } else {
                    log.info("机具已绑定，需要换绑，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
                }
            }

            return yxyTradeService.bindAndCreateReward(merchantNo, terminalSn, bindTime, merchant21.getUserBaseId(), terminal21.getChannelId());
        }

        return Result.builder().success();
    }

    /**
     * 交易通知
     *
     * @param jsonObject
     * @return
     */
    @Override
    public Result eposTransactionNotify(JSONObject jsonObject) {
        if (commonService.repeatSubmit("callbackXiaolu-transactionNotify:" + jsonObject.getString("logno"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }

        String merchantNo = jsonObject.getString("mercid");

        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);

        if (Objects.isNull(merchant21)) {
            log.error("拉卡拉交易推送,商户不存在.");
            return Result.builder().fail();
        }

        Terminal21 terminal21 = rpcYxyTerminalService.getTerminalBySn(jsonObject.getString("termphyno"));
        if (Objects.isNull(terminal21)) {
            log.error("易生格式化交易推送,机具号不存在，{}", jsonObject.toJSONString());
            return Result.builder().fail();
        }
        jsonObject.put("tradetime", DateUtil.formatDate(DateUtil.formatDate(jsonObject.getString("orderdat") + " " + jsonObject.getString("ordertime"),
                "yyyyMMdd HHmmss"), "yyyy-MM-dd HH:mm:ss"));
        if (StringUtils.isBlank(terminal21.getBindUserBaseId())) {
            log.info("商终未绑定，调用绑机接口");
            Result bindResult = yxyTradeService.bindAndCreateReward(merchantNo, terminal21.getTerminalSn(),
                    jsonObject.getString("tradetime"), merchant21.getUserBaseId(), terminal21.getChannelId());
            if (bindResult.isFail()) {
                log.error("拉卡拉交易推送,商户不存在，调用Rpc接口绑机失败");
                return Result.builder().fail();
            }
            // 商终绑定后，再次查询商户信息
            merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
        }

        // 格式化为 payTransaction
        PayTransaction payTransaction = payTransactionFormat(jsonObject, merchant21);

        if (Objects.nonNull(payTransaction)) {
            // 保存交易
            return dealTrade(payTransaction);
        }
        return Result.builder().success();
    }

    /**
     * 调用绑机接口
     *
     * @param merchantNo
     * @param sn
     * @param bindTime
     * @return
     */
    private Terminal callbackBind(String merchantNo, String sn, String bindTime) {
        // 调用绑机接口
        RpcYxyCallbackBindDTO dto = new RpcYxyCallbackBindDTO();
        dto.setMerchantNo(merchantNo);
        dto.setMerchantBindTime(LocalDateUtils.stringToLocalDateTime(bindTime));
        dto.setSn(sn);

        log.info("rpc调用terminal绑定机具");
        Result<Terminal> terminalResult = rpcYxyTerminalService.callbackBind(dto);
        if (Objects.isNull(terminalResult) || terminalResult.isFail()) {
            log.error("调用绑机接口处理失败，{}", sn);
            return null;
        }
        return terminalResult.getData();
    }

    /**
     * 生成交易对象
     *
     * @param jTrade
     * @return
     */
    public PayTransaction payTransactionFormat(JSONObject jTrade, Merchant21 merchant21) {
        log.info("小陆交易推送入参:{}", JSONObject.toJSONString(jTrade));
        PayTransaction payTransaction = new PayTransaction();

        payTransaction.setMerchantId(merchant21.getMerchantId());
        payTransaction.setMerchantNo(jTrade.getString("mercid"));

        payTransaction.setUserBaseId(merchant21.getUserBaseId());
        payTransaction.setMerchantName(merchant21.getMerchantName());
        payTransaction.setOrderNo(jTrade.getString("logno"));
        payTransaction.setTransactionNo(jTrade.getString("logno"));
        payTransaction.setSysRef(jTrade.getString("logno"));
        payTransaction.setTransactionAmount(jTrade.getBigDecimal("txnamt"));
        payTransaction.setTransactionFee(jTrade.getBigDecimal("ssfee"));

        payTransaction.setCardFlag(formatCardFlag(jTrade.getString("paychannel")));

        payTransaction.setTerminalId(jTrade.getString("termphyno"));
        payTransaction.setSn(jTrade.getString("termphyno"));
        payTransaction.setTransactionCardType(payTransaction.getCardFlag());
        payTransaction.setStatus(PayTransactionEnum.TransactionStatus.STATUS_10.getCode());
        payTransaction.setRate(merchant21.getRateCredit());
        LocalDateTime transTime = LocalDateTime.now();
        if (StringUtils.isNotBlank(jTrade.getString("tradetime"))) {
            transTime = LocalDateUtils.stringToLocalDateTime(jTrade.getString("tradetime"), DateFormat.DATETIME_DEFAULT.getPartten());
        }

        payTransaction.setTransactionTime(transTime);
        payTransaction.setTransactionMonth(LocalDateUtils.localDateTimeByFormat(transTime, DateFormat.DATE_MONTH.getPartten()));
        payTransaction.setTransactionDay(LocalDateUtils.localDateTimeByFormat(transTime, DateFormat.DATE_COMPACT.getPartten()));
        if (StringUtils.isEmpty(jTrade.getString("txf"))) {
            payTransaction.setFeeAmt(BigDecimal.ZERO);
        } else {
            payTransaction.setFeeAmt(jTrade.getBigDecimal("txf"));
        }

        payTransaction.setWithdrawalStatus(PayTransactionEnum.WithdrawalStatusEnum.STATUS_40.getCode());

        payTransaction.setChannelId(merchant21.getChannelId());
        payTransaction.setPlatNo(PlatNoEnums.YXY.getCode());
        payTransaction.setIsDel(false);
        payTransaction.setTransType(formatPledgeStatus(jTrade));
        // 分润标识
        payTransaction.setProfitFlag(checkIsProfitFlag(payTransaction));

        return payTransaction;
    }

    /**
     * 保存易生的交易
     *
     * @param payTransaction
     * @return
     */
    public Result dealTrade(PayTransaction payTransaction) {
        KLog.info("保存小陆交易 入参:{}", payTransaction.toJSON());
        try {
            // 存交易
            YxyTradeService yxyTradeService = SpringContextUtils.getBean(YxyTradeService.class);
            payTransaction = yxyTradeService.saveTrade(payTransaction);

            if (Objects.isNull(payTransaction) || !PayTransactionEnum.TransactionStatus.STATUS_10.isEquals(payTransaction.getStatus())) {
                return Result.builder().success();
            }

            Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(payTransaction.getMerchantNo());
            if (Objects.isNull(merchant21)) {
                log.error("保存小陆交易, 商户为空，merchantNo={}", payTransaction.getMerchantNo());
                return Result.builder().fail(BizCodeMessages.MERCHANT_UN_EXISTED,
                        "保存小陆交易, 商户为空，merchantNo={}", payTransaction.getMerchantNo());
            }

            // 押金、流量卡类型，商户未返现才调激活返现
            if (StringUtils.equals(payTransaction.getTransType(), LklTransTypeEnum.TYPE_412001.getTransType())) {
                Merchant21 merchant21Up = new Merchant21();
                merchant21Up.setMerchantId(merchant21.getMerchantId());
                merchant21Up.setPledgeCashSuccessTime(payTransaction.getTransactionTime());
                merchant21Up.setPledgeCashOrderNo(payTransaction.getOrderNo());
                merchant21Up.setPledgeCashSerialNo(payTransaction.getOrderNo());
                merchant21Up.setPledgeCashStatus(MerchantEnum.PledgeCashStatusEnum.STATUS_200.getCode());
                merchant21Mapper.updateByPrimaryKeySelective(merchant21Up);
            }
            // 调激活返现
            CheckActiveRewardYxyDTO dto = new CheckActiveRewardYxyDTO();
            dto.setChannelId(payTransaction.getChannelId());
            dto.setTerminalSn(payTransaction.getSn());
            dto.setPlatNo(PlatNoEnums.YXY.getCode());
            dto.setTradeAmount(payTransaction.getTransactionAmount());
            dto.setTradeTime(payTransaction.getTransactionTime());
            dto.setUserBaseId(payTransaction.getUserBaseId());
            dto.setOrderNo(payTransaction.getOrderNo());
            KLog.info("小陆调用检查激活返现:{}", dto.toJSON());
            Result<Void> voidResult = merchantYxyRewardApiService.checkYxyReward(dto);
            KLog.info("小陆检查激活返现结束:{}", voidResult.toString());
            // 计入分润
            payEposService.profitOpt(payTransaction);
            // 私信调用
            payEposService.sendTransactionLetter(payTransaction);

        } catch (Exception e) {
            KLog.error("小陆交易回调处理失败:{},入参:{}", e.getMessage(), payTransaction.toJSON(), e);
            return Result.builder().fail(BizCodeMessages.DB_WRITE_ERR, "小陆交易回调处理失败");
        }
        return Result.builder().success();
    }

    /**
     * 格式化卡类型
     *
     * @param payChannel
     * @return
     */
    private String formatCardFlag(String payChannel) {

        if (StringUtils.equalsAny(payChannel, "02")) {
            return PayTransactionEnum.CardFlagEnum.WECHAT.getCode();
        } else if (StringUtils.equalsAny(payChannel, "01")) {
            return PayTransactionEnum.CardFlagEnum.ALIPAY.getCode();
        } else if (StringUtils.equalsAny(payChannel, "06", "10")) {
            return PayTransactionEnum.CardFlagEnum.CREDIT_CARD.getCode();
        } else if (StringUtils.equalsAny(payChannel, "05", "09")) {
            return PayTransactionEnum.CardFlagEnum.BORROW_CARD.getCode();
        } else if (StringUtils.equalsAny(payChannel, "03", "04", "07")) {
            return PayTransactionEnum.CardFlagEnum.UNIONCODE.getCode();
        }
        return payChannel;
    }


    /**
     * 判断交易状态
     *
     * @param respCode 交易状态
     * @return
     */
    private Short formatTradeStatus(String respCode) {
        if (StringUtils.equals(respCode, "00")) {
            return PayTransactionEnum.TransactionStatus.STATUS_10.getCode();
        }

        return PayTransactionEnum.TransactionStatus.STATUS_20.getCode();
    }


    /**
     * 判断押金状态
     *
     * @param jTrade 交易实体
     * @return
     */
    private String formatPledgeStatus(JSONObject jTrade) {
        if (StringUtils.equals(jTrade.getString("paychannel"), "11")) {
            return LklTransTypeEnum.TYPE_412001.getTransType();
        } else {
            return LklTransTypeEnum.TYPE_012001.getTransType();
        }
    }

    // 判断是否计入分润
    private boolean checkIsProfitFlag(PayTransaction payTransaction) {

        // 贷记卡且非押金交易,非流量卡交易才计入分润
        if (StringUtils.equalsAny(payTransaction.getCardFlag(),
                PayTransactionEnum.CardFlagEnum.ALIPAY.getCode(),
                PayTransactionEnum.CardFlagEnum.WECHAT.getCode(),
                PayTransactionEnum.CardFlagEnum.CREDIT_CARD.getCode(),
                PayTransactionEnum.CardFlagEnum.UNIONCODE_CREDIT.getCode(),
                PayTransactionEnum.CardFlagEnum.UNIONCODE.getCode())) {
            return true;
        }

        return false;
    }

    @Override
    public Result eposTerminalBindNotify(JSONObject jsonObject) {
        log.info("小陆电签机具绑定通知eposTerminalBindNotify：{}", jsonObject);

        if (commonService.repeatSubmit("callbackXiaolu-eposTerminalBindNotify:" + jsonObject.getString("termphyno"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }

        String merchantNo = jsonObject.getString("mercid");
        String terminalSn = jsonObject.getString("termphyno");
        String bindTime = DateUtil.getDateTime();

        Terminal21 terminal21 = rpcYxyTerminalService.getTerminalBySn(terminalSn);
        if (Objects.isNull(terminal21)) {
            log.error("小陆电签机具绑定通知,机具不存在.");
            return Result.builder().fail();
        }

        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
        if (Objects.isNull(merchant21)) {
            log.info("小陆电签机具绑定通知,商户不存在插入");
            return Result.builder().fail();
        }

        String bindUserBaseId = terminal21.getBindUserBaseId();
        if (StringUtils.isNotEmpty(bindUserBaseId)) {
            if (StringUtils.equals(merchant21.getUserBaseId(), bindUserBaseId)) {
                log.info("机具已绑定，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
                return Result.builder().success();
            } else {
                log.info("机具已绑定，需要换绑，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
            }
        }

        return yxyTradeService.bindAndCreateReward(merchantNo, terminalSn, bindTime, merchant21.getUserBaseId(), terminal21.getChannelId());
    }

    @Override
    public Result sposMerchantNotify(JSONObject jsonObject, String aesKey) {
        log.info("小陆商户通知sposMerchantNotify，key:{}", aesKey);
        if (commonService.repeatSubmit("callbackXiaolu-sposMerchantNotify:" + jsonObject.getString("mercid"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }
        String merchantNo = jsonObject.getString("mercid");
        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);

        String secret = jsonObject.getString("reqdata");
        JSONObject jSecret = new JSONObject();
        if (jsonObject.containsValue("lakala.2021")) {
            jSecret = JSONObject.parseObject(secret);
        } else if (!StringUtils.isEmpty(secret)) {
            jSecret = JSONObject.parseObject(XiaoLuUtil.sm4Decrypt(aesKey, secret));
            log.info("小陆商户通知sposMerchantNotify，解密后:{}", jSecret.toJSONString());
        }
        if (Objects.isNull(merchant21)) {
            SaveMerchantDTO dto = new SaveMerchantDTO();
            dto.setMerchantNo(merchantNo);
            dto.setAgentNo(jsonObject.getString("agentid"));
            dto.setRegistTime(DateUtil.getDateTime());
            dto.setAuthTime(DateUtil.getDateTime());
            dto.setActiveTime(DateUtil.getDateTime());
            dto.setUserName(jsonObject.getString("mercname"));
            dto.setPhone(merchantNo);

            dto.setRealName(jSecret.getString("name"));
            dto.setIdCard(jSecret.getString("idcard"));

            dto.setChannelId(ChannelIdEnums.YRB_XIAOLU_SPOS.getCode());
            dto.setPushWay(YsPaySaveMerchantDTO.PUSH_WAY_MERCHANT);
            return merchantYxyApiService.saveMerchant(dto);
        } else {
            Merchant21 merchant21Update = new Merchant21();
            merchant21Update.setMerchantId(merchant21.getMerchantId());
            merchant21Update.setRealName(jSecret.getString("name"));
            merchant21Update.setIdCard(jSecret.getString("idcard"));
            merchant21Mapper.updateByPrimaryKeySelective(merchant21Update);
            return Result.builder().success();
        }
    }

    @Override
    public Result sposTerminalBindNotify(JSONObject jsonObject) {
        log.info("小陆商户机具绑定通知sposTerminalBindNotify");

        if (commonService.repeatSubmit("callbackXiaolu-sposTerminalBindNotify:" + jsonObject.getString("termphyno"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }

        String merchantNo = jsonObject.getString("mercid");
        String terminalSn = jsonObject.getString("termphyno");
        String bindTime = DateUtil.getDateTime();

        Terminal21 terminal21 = rpcYxyTerminalService.getTerminalBySn(terminalSn);
        if (Objects.isNull(terminal21)) {
            log.error("小陆商户机具绑定通知,机具不存在.");
            return Result.builder().fail();
        }

        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
        if (Objects.isNull(merchant21)) {
            log.info("小陆商户机具绑定通知,商户不存在插入");
            return Result.builder().fail();
        }

        String bindUserBaseId = terminal21.getBindUserBaseId();
        if (StringUtils.isNotEmpty(bindUserBaseId)) {
            if (StringUtils.equals(merchant21.getUserBaseId(), bindUserBaseId)) {
                log.info("机具已绑定，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
                return Result.builder().success();
            } else {
                log.info("机具已绑定，需要换绑，terminalSn={}, merchantNo={}", terminalSn, merchantNo);
            }
        }

        return yxyTradeService.bindAndCreateReward(merchantNo, terminalSn, bindTime, merchant21.getUserBaseId(), terminal21.getChannelId());
    }

    @Override
    public Result sposTransactionNotify(JSONObject jsonObject) {
        log.info("小陆微智能交易回调");
        if (commonService.repeatSubmit("callbackXiaolu-sposTransactionNotify:" + jsonObject.getString("logno"))) {
            log.info("重复推送跳过:{}", jsonObject.toJSONString());
            return Result.builder().fail(BizCodeMessages.VALIDATOR_REPEAT_SUBMIT, "重复请求");
        }

        String merchantNo = jsonObject.getString("mercid");

        Merchant21 merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);

        if (Objects.isNull(merchant21)) {
            log.error("小陆微智能交易回调,商户不存在.");
            return Result.builder().fail();
        }

        Terminal21 terminal21 = rpcYxyTerminalService.getTerminalBySn(jsonObject.getString("termphyno"));
        if (Objects.isNull(terminal21)) {
            log.error("小陆微智能交易回调,机具号不存在，{}", jsonObject.toJSONString());
            return Result.builder().fail();
        }
        jsonObject.put("tradetime", DateUtil.formatDate(DateUtil.formatDate(jsonObject.getString("orderdat") + " " + jsonObject.getString("ordertime"),
                "yyyyMMdd HHmmss"), "yyyy-MM-dd HH:mm:ss"));
        if (StringUtils.isBlank(terminal21.getBindUserBaseId())) {
            log.info("小陆微智能交易回调商终未绑定，调用绑机接口");
            Result bindResult = yxyTradeService.bindAndCreateReward(merchantNo, terminal21.getTerminalSn(),
                    jsonObject.getString("tradetime"), merchant21.getUserBaseId(), terminal21.getChannelId());
            if (bindResult.isFail()) {
                log.error("小陆微智能交易回调,商户不存在，调用Rpc接口绑机失败");
                return Result.builder().fail();
            }
            // 商终绑定后，再次查询商户信息
            merchant21 = merchantYxyApiService.getMerchant21ByMerchantNo(merchantNo);
        }

        // 格式化为 payTransaction
        PayTransaction payTransaction = payTransactionFormat(jsonObject, merchant21);

        if (Objects.nonNull(payTransaction)) {
            // 保存交易
            return dealTrade(payTransaction);
        }
        return Result.builder().success();
    }

    @Override
    public Result sposIccNotify(JSONObject jsonObject) {
        String merchantNo = jsonObject.getString("mercid");

        Merchant21Example merchant21Example = new Merchant21Example();
        merchant21Example.createCriteria().andMerchantNoEqualTo(merchantNo);
        List<Merchant21> merchant21List = merchant21Mapper.selectByExample(merchant21Example);
        if (CollectionUtils.isEmpty(merchant21List)) {
            KLog.error(BizCodeMessages.MERCHANT_UN_EXISTED, "商户号未找到商户");
            return Result.builder().success();
        }
        String merchantUserBaseId = merchant21List.get(0).getUserBaseId();
        int transTableIndex = PayTransactionUtil.getTransTableIndex(merchantUserBaseId);
//        String feeTime = DateUtil.formatDate(DateUtil.formatDate(jsonObject.getString("feetime"), "yyyyMMddHHmmss"), "yyyy-MM-dd HH:mm:ss");
        LocalDateTime feeTimeLocalTime = LocalDateUtils.stringToLocalDateTime(jsonObject.getString("feetime"), "yyyyMMddHHmmss");
        List<PayTransaction> ptList = new ArrayList<>();
        for (int i = 0; i < 60; i++) {
            ptList = transactionPayTransactionMapper.getByMerchantNoTransTime(transTableIndex,
                    merchantNo, LocalDateUtils.formatByDefaultFormat(feeTimeLocalTime)
                    , 1);
            if (CollectionUtils.isEmpty(ptList)) {
                ptList = transactionPayTransactionMapper.getByMerchantNoTransTime(transTableIndex,
                        merchantNo, null, 1);
                if (CollectionUtils.isEmpty(ptList)) {
                    sleep(1000);
                } else {
                    break;
                }
            } else {
                break;
            }
        }
        if (CollectionUtils.isEmpty(ptList)) {
            KLog.info("原交易不存在, 跳过不处理");
            return Result.builder().success();
        }

        PayTransaction payTransaction = ptList.get(0);
        BigDecimal iccAmount = payTransaction.getIccPayAmt();
        if (Objects.nonNull(iccAmount) && iccAmount.compareTo(BigDecimal.ZERO) > 0) {
            KLog.info("已存在流量费, 跳过不处理 {}");
            return Result.builder().fail(BizCodeMessages.MALL_ORDER_STATUS_ERR);
        }

        // 扣款金额
        iccAmount = jsonObject.getBigDecimal("receivefee");

        // 更新交易表
        PayTransaction ptUpdate = new PayTransaction();
        ptUpdate.setPayTransactionId(payTransaction.getPayTransactionId());
        ptUpdate.setUserBaseId(payTransaction.getUserBaseId());
        ptUpdate.setOrderNo(payTransaction.getOrderNo());
        ptUpdate.setSid(jsonObject.getString("feeid"));
        ptUpdate.setIccPayAmt(iccAmount);
        ptUpdate.setTransType(LklTransTypeEnum.TYPE_012003.getTransType());
        ptUpdate.setVersion(payTransaction.getVersion());
        ptUpdate.setRemarks("流量费交易");
        payTransactionOrderService.updateById(ptUpdate);
        // 调激活返现
        CheckActiveRewardYxyDTO dto = new CheckActiveRewardYxyDTO();
        dto.setChannelId(payTransaction.getChannelId());
        dto.setTerminalSn(payTransaction.getSn());
        dto.setPlatNo(PlatNoEnums.YXY.getCode());
        dto.setTradeAmount(iccAmount);
        dto.setTradeTime(feeTimeLocalTime);
        dto.setUserBaseId(payTransaction.getUserBaseId());
        dto.setOrderNo(payTransaction.getOrderNo());
        KLog.info("小陆微智能流量卡交易调用检查激活返现:{}", dto.toJSON());
        Result<Void> voidResult = merchantYxyRewardApiService.checkYxyReward(dto);
        KLog.info("小陆微智能流量卡交易检查激活返现结束:{}", voidResult.toString());

        return Result.builder().success();
    }
}